home *** CD-ROM | disk | FTP | other *** search
- IF NOT lasm
- .printx * CPXCOM.ASM *
- ENDIF ; NOT lasm
- ; KERMIT - (Celtic for "FREE")
- ;
- ; This is the CP/M-80 implementation of the Columbia University
- ; KERMIT file transfer protocol.
- ;
- ; Version 4.0
- ;
- ; Copyright June 1981,1982,1983,1984,1985
- ; Columbia University
- ;
- ; Originally written by Bill Catchings of the Columbia University Center for
- ; Computing Activities, 612 W. 115th St., New York, NY 10025.
- ;
- ; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben,
- ; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many
- ; others.
- ;
- ; This file contains part common code required for most if not all
- ; systems. Specifiacally, SYSINIT, INIADR, MOVER, and DELAY to name
- ; the most important ones.
- ;
- ; revision history:
- ;
- ; edit 1, 21st July 1987 by OBSchou. Regretably, I have had to include
- ; some system dependent IFs, mainly for CRT, TORCH and OSI. Inclusion
- ; here means simpler family files later on. (Regrettably, the delay
- ; loop for APMMDM differs too.)
- ;
- ; Set the fuzzy timeout value. Range is 1 (VERY short) through 0ffffH to zero
- ; (maximum). The actual duration is a function of the loop length and the
- ; processor speed. For now, we'll make it zero for everybody, but feel free
- ; to change it for your system.
- ; [OBS] make it a little less than max, say 1000H. More useful.
- fuzval EQU 1000H
-
- ;
- ; System-dependent initialization
- ; Called once at program start.
- sysinit:
- ;
- ; [13] Had to move this call to here, as the prtstr routine needs this
- ; before the config message is sent out. It has only been moved.
- ;
- call iniadr ;Initialize the BIOS addresses
- mvi c,gtiob ;Get current I/O byte
- call bdos ;From CP/M
- sta coniob ;Remember where console is
- mvi c,getvnm ; get the BDOS version number (e.g. 22H, 31H)
- call bdos
- mov a,l
- sta bdosvr ; and store it away for future reference
- lxi d,cfgmsg ; "configured for "
- call prtstr
- lxi d,sysver ; get configuration we're configured for
- call prtstr ; print it.
- ;
- ; If we're set up to do special terminal handling, say what kind
- ; of terminal we expect... (unless it's the generic 'crt')
- IF termin
- lxi d,witmsg ; " with "
- call prtstr
- lxi d,ttytyp ; terminal type
- call prtstr
- ENDIF;termin
- call prcrlf ; print CR/LF
- ;
- ; now, to work...
- ;
- ; locate large buffer for multi-sector I/O
- ; What we want to do here is find the ccp. Space between ovlend and the ccp
- ; is available for buffering, except we don't want to use more than maxsec
- ; buffers (if we use too many, the remote end could time out while we're
- ; writing to disk). maxsec is system-dependent, but for now we'll just
- ; use 8Kbytes. If you get retransmissions and other protocol errors after
- ; transferring the first maxsec sectors, lower maxsec.
-
- maxsec EQU (8*1024)/bufsiz ; 8K / number of bytes per sector
-
- lxi h,ovlend ; get start of buffer
- shld bufadr ; store in linkage section
- mvi a,maxsec ; get size of buffer, in sectors
- sta bufsec ; store that, too.
-
- call sysxin ; call system specific init code
-
- ret ; return from system-dependent routine
-
- bdosvr: ds 1 ; space to save the BDOS version number
- IF NOT iobyt
- coniob: ds 1 ; space to save copy of IO byte
- ENDIF ;NOT iobyt
- ;
- ; This one is hopefully the last "improvement" in view of GENERIC
- ;Kermit. It uses for Character-I/O the BIOS-routines ( instead of the
- ;"normal" BDOS routines. What does it give us (hopefully) : More speed,
- ;higher chance of success ( I/O byte implemented in BIOS [if at all]),
- ;but no "extra" device handling - that's done by BDOS.
- ;
- ; How do we "get" the call-adresses? Location 0 has a JMP Warm-Boot
- ;in CP/M which points into the second location of the BIOS JMP-Vector. The
- ;next three locations of the JMP-Vector point to the CONSTAT,CONIN,CONOUT
- ;BIOS-routines. CONOUT wants the character in C.
- ;
- ;- Bernie Eiben
-
- iniadr: lhld 1 ;get BIOS Warmstart-address
- lxi d,3 ;next adress is CONSTAT in BIOS
- dad d
- shld bconst+1 ;stuff it into the call-instruction
- lxi d,3 ;next adress is CONIN in BIOS
- dad d
- shld bconin+1 ;
- lxi d,3 ;next adress is CONOUT in BIOS
- dad d
- shld bcnout+1
- lxi d,3 ;next address is LIST in BIOS
- dad d
- shld blsout+1
- lxi d,10*3 ; get printer status routine
- dad d
- shld bprtst
- ret ;And return
-
- bconst: jmp $-$ ;Call BIOS directly (filled in by iniadr)
-
- bconin: jmp $-$ ;Call BIOS directly (filled in by iniadr)
-
- bcnout: jmp $-$ ;Call BIOS directly (filled in by iniadr)
-
- blsout: jmp $-$ ; ....
-
- bprtst: jmp $-$ ; Call BIOS directly for printer status
-
- IF NOT apmmdm ; Shame about this, but the Apple needs a different delay
- ;
- ;[cjc] Delay routine. Called with time (hundredths of seconds) in A.
- ; The inner loop delays 1001 T-states, assuming no wait states are
- ; inserted; this is repeated CPUSPD times, for a total delay of just
- ; over 0.01 second. (CPUSPD should be set to the system clock rate,
- ; in units of 100KHz: for an unmodified Kaypro II, that's 25 for
- ; 2.5 MHz. Some enterprising soul could determine whether or not the
- ; Kaypro actually inserts a wait state on instruction fetch (a common
- ; practice); if so, the magic number at delay2 needs to be decreased.
- ; (We also neglect to consider time spent at interrupt level).
- ;
- ; called by: sendbr
- ; destroys BC
-
- delay: mvi c,cpuspd ; Number of times to wait 1000 T-states to
- ; make .01 second delay
- delay2: mvi b,70 ; Number of times to execute inner loop to
- ; make 1000 T-state delay
- delay3: dcr b ; 4 T-states (* 70 * cpuspd)
- jnz delay3 ; 10 T-states (* 70 * cpuspd)
- dcr c ; 4 T-states (* cpuspd)
- jnz delay2 ; 10 T-states (* cpuspd)
- ; total delay: ((14 * 70) + 14) * cpuspd
- ; = 1001 * cpuspd
- dcr a ; 4 T-states
- jnz delay ; 10 T-states
- ret ; grand total: ((1001 * cpuspd) + 14) * a
- ENDIF ; NOT apmmdm
- ;
- ;
- ; Set up screen display for file transfer
- ; called with kermit version in DE
- ;
- sysscr: push d ; save version for a bit
- lxi d,outlin ; clear screen, position cursor
- call prtstr ; do it
- pop d ; get Kermit's version
- IF NOT (osi OR crt) ; got cursor control?
- call prtstr ; print it
- mvi e,'[' ; open bracket
- call outcon ; print it (close bracket is in outln2)
- lxi d,sysver ; get name and version of system module
- call prtstr
- lxi d,outln2 ; yes, print field names
- call prtstr
- lda dbgflg ; is debugging enabled?
- ora a
- rz ; finished if no debugging
- lxi d,outln3 ; set up debugging fields
- call prtstr
- ENDIF;NOT (osi OR crt)
- ret
- ;
- ; Calculate free space for current drive
- ; returns value in HL
- sysspc:
- lda bdosvr ;cpm3's alloc vect may be in another bank
- cpi 30H ;cpm3 or later?
- jm cp2spc ;no: use cp/m 2 algorithm
- lda fcb ;If no drive, get
- ora a ; logged in drive
- jz dir180
- dcr a ;FCB drive A=1 normalize to be A=0
- jmp dir18a
-
- dir180: mvi c,rddrv
- call bdos
- dir18a: mov e,a ;drive in e
- mvi c,getfs ;get free space BDOS funct
- call bdos ;returns free recs (3 bytes in buff..buff+2)
- mvi b,3 ;conv recs to K by 3 bit shift
- dir18b: xra a ;clear carry
- mvi c,3 ;for 3 bytes
- lxi h,buff+3 ;point to addr + 1
- dir18c: dcx h ;point to less sig. byte
- mov a,m ;get byte
- rar ;carry -> A -> carry
- mov m,a ;put back byte
- dcr c ;for all bytes (carry not mod)
- jnz dir18c
- dcr b ;shift 1 bit 3 times
- jnz dir18b
- mov e,m ;get least sig byte
- inx h
- mov d,m ;get most sig byte
- xchg ;get K free in HL
- ret
-
- ; the rest are CP/M 2.2 systems, so use the alloc vector
- cp2spc: mvi c,getalv ;Address of CP/M Allocation Vector
- call bdos
- xchg ;Get its length
- lhld bmax
- inx h
- lxi b,0 ;Initialize Block count to zero
- dir19: push d ;Save allocation address
- ldax d
- mvi e,8 ;set to process 8 blocks
- dir20: ral ;Test bit
- jc dir20a
- inx b
- dir20a: mov d,a ;Save bits
- dcx h
- mov a,l
- ora h
- jz dir21 ;Quit if out of blocks
- mov a,d ;Restore bits
- dcr e ;count down 8 bits
- jnz dir20 ;do another bit
- pop d ;Bump to next count of Allocation Vector
- inx d
- jmp dir19 ;process it
-
- dir21: pop d ;Clear Allocation vector from stack
- mov l,c ;Copy block to 'HL'
- mov h,b
- lda bshiftf ;Get Block Shift Factor
- sui 3 ;Convert from records to thousands
- rz ;Skip shifts if 1K blocks
- dir22: dad h ;Multiply blocks by 'K per Block'
- dcr a
- jnz dir22
- ret
-
- ; +----|----|----|----|----|----|----|...
- ; 1 |
- ; 2 | Kermit-80 v4.0 [system]
- ; 3 |
- ; 4 |Number of packets: ____
- ; 5 |Number of retries: ____
- ; 6 |File name: ____________
- ; 7 |<error>...
- ; 8 |<status>...
- ; 9 |RPack: ___(if debugging)...
- ; 10 |
- ; 11 |SPack: ___(if debugging)...
- ; 12 |
- ; 13 |Kermit-80 A:> (when finished)
- ;
- ; For the PX-8, the display looks like:
- ; 5 10 15 20 25 30 35 40 45 50 55
- ; +----|----|----|----|----|----|----|----|----|----|----|----|----
- ; 1 |Kermit-80 v4.05 [Epson PX-8] Number of retries: ____
- ; 2 |Number of packets: ____ File name: ________.___
- ; 3 |<error>...
- ; 4 |<status>...
- ; 5 |RPack: ___ (if debugging)...
- ; 6 |
- ; 7 |SPack: ___ (if debugging)...
- ; 8 |
- ; 9 |Kermit-80 A:> (when finished)
- ;
-
- IF NOT px8 ; [29]
- nppos EQU 4*100h+20
- rtpos EQU 5*100h+20
- fnpos EQU 6*100h+12
- errlin EQU 7
- stlin EQU 8
- rplin EQU 9
- splin EQU 11
- prplin EQU 13
- ENDIF ; NOT px8
-
- IF px8
- nppos EQU 2*100h+20
- rtpos EQU 1*100h+59
- fnpos EQU 2*100h+51
- errlin EQU 3
- stlin EQU 4
- rplin EQU 5
- splin EQU 7
- prplin EQU 9
- ENDIF ; px8 [29]
-
-
- IF NOT (osi OR crt );[26]
- scrnp: lxi b,nppos
- jmp csrpos
-
- scrnrt: lxi b,rtpos
- jmp csrpos
-
- scrfln: lxi b,fnpos
- call csrpos
- clreol:
- lxi d,tk
- jmp prtstr
-
- screrr: lxi b,errlin*100H+1
- call csrpos
- jmp clreol
-
- scrst: lxi b,stlin*100H+1
- call csrpos
- jmp clreol
-
- rppos: lxi b,rplin*100H+8
- call csrpos
- jmp clreol
-
- sppos: lxi b,splin*100H+8
- call csrpos
- jmp clreol
-
- ; [29] Modify scrend to make the cursor line conditional on use of debugging
- ; This means that in most cases the entire file transfer will fit on PX-8 lcd
- scrend: lda dbgflg
- ora a
- jz scr1nd
- lxi b,prplin*100H+1 ; debugging in use [29]
- jmp scr2nd
- scr1nd: lxi b,rplin*100H+1 ; no debugging
- scr2nd: call csrpos
- clreos: lxi d,tj
- jmp prtstr
- ; [29] and nop out the rest for now...
- ;
- ;scrend: lxi b,prplin*100H+1
- ; call csrpos
- ;clreos: lxi d,tj
- ; jmp prtstr
- ENDIF;NOT (osi OR crt ) [26]
-
-
- IF osi OR crt ; no cursor control
- scrnp: mvi e,' '
- jmp outcon
-
- scrnrt: mvi e,' '
- call outcon
- mvi e,'%'
- jmp outcon
-
- scrfln:
- screrr:
- scrst:
- scrend: jmp prcrlf ;Print CR/LF [Toad Hall]
-
- rppos: lxi d,prpack
- jmp prtstr
-
- sppos: lxi d,pspack
- jmp prtstr
- ENDIF;osi OR crt
-
- ; Some frequently-used routines (duplicates of those in CPSMIT):
- ; prcrlf - output a CR/LF
- ; prtstr - output string in DE
- ; rskp - return, skipping over error return
- prcrlf: lxi d,crlf
- prtstr:
- ; [17] added this to avoid prtstr.. emulate function 9 call.
- ; Works on most machines.
- IF (torch OR px8 OR z80mu)
- ;
- ; Modified print string as the CP/N (for Nut) system traps control
- ; characters in a function 9 call.. rot its cotton socks.
- push h
- push d
- push b
- prtst1:
- ldax d
- inx d
- cpi '$' ; if a dollar then end of string
- jz prtst2
- push d
- mov e,a
- mov c,a ; also to c if its via conout in BIOS
- call outcon ; send it to the screen
- pop d
- jmp prtst1
-
- prtst2: pop b
- pop d
- pop h
- ret ; regs restored.. just in case
- ENDIF ;(torch OR px8 OR z80mu)
-
- IF NOT (torch OR px8 or z80mu) ;ie any machine that can send ctrl chrs via dos call 9
- PUSH H
- PUSH D
- push b
- mvi c,9 ; Dos call 9 (print a string)
- call bdos
- pop b
- POP D
- POP H
- ret ; all done for good machines
- ENDIF ;NOT (torch OR px8 OR z80mu)
-
- ;
- ; rskp - return to calling address + 3.
- rskp: pop h ; Get the return address
- inx h ; Increment by three
- inx h
- inx h
- pchl
-
- ; Copy block of data
- ; source in HL, destination in DE, byte count in BC
- ; called by: cpxsys, mfname
- ;
- mover:
- ;IF NOT z80 ; 8080's have to do it the hard way
- ;OBS assume its an 8080 for now - this will work on Z80s anyway.
- mov a,m
- stax d
- inx h
- inx d
- dcx b
- mov a,b
- ora c
- jnz mover
- ;ENDIF;NOT z80
- ;IF z80
- ; db 0EDh,0B0h ; Z80 LDIR instruction
- ;ENDIF;z80
- ret
-
- ;
- ; Miscellaneous messages
- ;
- crlf: db cr,lf,'$'
- cfgmsg: db 'configured for $'
- witmsg: db ' with $' ; Its included if we get here ('with terminal')
-
- IF NOT (osi OR crt OR px8) ; [29] got cursor control?
- outln2: db ']',cr,lf,cr,lf,'Number of packets:'
- db cr,lf,'Number of retries:'
- db cr,lf,'File name:$'
- ENDIF;NOT (osi OR crt OR px8)
-
- IF px8 ; [29]
- outln2: db '] Number of retries:', cr, lf
- db 'Number of packets: File name:$'
- ENDIF ; px8 [29]
-
- IF NOT (osi OR crt) ; [29]
- outln3: db cr,lf,cr,lf ; debugging messages
- db cr,lf,'Rpack:'
- db cr,lf ; Blank line in case of long packet
- db cr,lf,'Spack:$'
- ENDIF ; NOT (osi OR crt) [29]
-
- IF lasm
- LINK CPXSWT.ASM
- ENDIF ;lasm
-
-